package com.yvon.maple.service.system.controller;

import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Lists;
import com.yvon.boot.common.result.ResponseData;
import com.yvon.boot.common.validation.group.CreateGroup;
import com.yvon.boot.common.validation.group.UpdateGroup;
import com.yvon.boot.excel.ExcelUtil;
import com.yvon.boot.mybatis.page.ListData;
import com.yvon.boot.mybatis.search.BaseQuery;
import com.yvon.maple.cloud.api.base.feign.FileFeignClient;
import com.yvon.maple.cloud.web.data.AbstractController;
import com.yvon.maple.cloud.web.filter.LoginUserUtil;
import com.yvon.maple.constants.FileKey;
import com.yvon.maple.service.system.bo.UserBo;
import com.yvon.maple.service.system.dto.UserDTO;
import com.yvon.maple.service.system.dto.UserRoleDTO;
import com.yvon.maple.service.system.entity.User;
import com.yvon.maple.service.system.query.UserQuery;
import com.yvon.maple.service.system.service.UserDeptService;
import com.yvon.maple.service.system.service.UserRoleService;
import com.yvon.maple.service.system.service.UserService;
import com.yvon.maple.service.system.vo.RegisterVO;
import com.yvon.maple.service.system.vo.ResetPasswordVO;
import com.yvon.maple.service.system.vo.UpdatePasswordVO;
import com.yvon.maple.service.system.vo.UserVO;
import com.yvon.maple.utils.DataConverter;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

import static com.yvon.maple.constants.SystemConstant.System.ROLE_USER_ID;

/**
 * @author : Yvon
 * @version : 1.0
 * @since : 2021/3/15
 */
@RestController
@RequestMapping(value = "/users")
@Api(value = "用户管理", tags = "系统服务 - 用户管理API")
public class UserController extends AbstractController<User, UserDTO, UserVO, UserService> {

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private UserDeptService userDeptService;

    @Autowired
    private FileFeignClient fileFeignClient;

    @ApiOperation(value = "注册")
    @PostMapping("/register")
    public ResponseData<UserDTO> register(@Validated @RequestBody RegisterVO registerVO) {
        User user = DataConverter.convert(registerVO, User.class);
        getService().save(user, Lists.newArrayList(ROLE_USER_ID));
        return success(entityToDto(user));
    }

    @ApiOperation(value = "新增")
    @PostMapping
    public ResponseData<UserDTO> add(@Validated(CreateGroup.class) @RequestBody UserVO userVO) {
        User user = voToEntity(userVO);
        getService().save(user, userVO.getRoleIds());
        return success(entityToDto(user));
    }

    @ApiOperation(value = "更新")
    @PutMapping
    public ResponseData<UserDTO> update(@Validated(UpdateGroup.class) @RequestBody UserVO userVO) {
        User user = voToEntity(userVO);
        getService().update(user, userVO.getRoleIds());
        return success(entityToDto(user));
    }

    @ApiOperation(value = "修改密码")
    @PutMapping("/updatePassword")
    public ResponseData<Boolean> updatePassword(@Validated @RequestBody UpdatePasswordVO vo) {
        return success(getService().updatePassword(vo));
    }

    @ApiOperation(value = "重置密码")
    @PutMapping("/resetPassword")
    public ResponseData<Boolean> resetPassword(@Validated @RequestBody ResetPasswordVO vo) {
        return success(getService().resetPassword(vo));
    }

    @ApiOperation(value = "查询")
    @GetMapping("/id/{id}")
    public ResponseData<UserDTO> getById(@PathVariable("id") Long id) {
        User user = getService().getById(id);
        return success(entityToDTO(user));
    }

    @ApiOperation(value = "删除")
    @DeleteMapping
    private ResponseData<Boolean> delete(@RequestBody List<Long> ids) {
        return success(getService().removeBatchByIds(ids));
    }

    @ApiOperation("检查邮箱是否唯一")
    @GetMapping("/checkEmailUnique")
    public ResponseData<Boolean> checkEmailUnique(@RequestParam("email") String email, @RequestParam(name = "id", required = false) Long id) {
        return success(getService().isUniqueness("email", email, id));
    }

    @ApiOperation("检查手机号是否唯一")
    @GetMapping("/checkPhoneUnique")
    public ResponseData<Boolean> checkPhoneUnique(@RequestParam("phone") String phone, @RequestParam(name = "id", required = false) Long id) {
        return success(getService().isUniqueness("phone", phone, id));
    }

    @ApiOperation("检查账号是否唯一")
    @GetMapping("/checkUsernameUnique")
    public ResponseData<Boolean> checkUsernameUnique(@RequestParam("username") String username, @RequestParam(name = "id", required = false) Long id) {
        return success(getService().isUniqueness("username", username, id));
    }

    @ApiOperation(value = "查询用户详细信息")
    @GetMapping("/detail/username")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户名", dataType = "string")
    })
    public ResponseData<UserDTO> getDetailByUsername(@RequestParam(value = "username", required = false) String username) {
        String userName = Objects.nonNull(username) ? username : LoginUserUtil.getUsername();
        User user = getService().getByUsername(userName);
        return success(entityToDTO(user));
    }


    @GetMapping({"/page"})
    @ApiOperation(value = "分页查询", notes = "分页查询API")
    public ResponseData<ListData<UserDTO>> findPage(@Valid UserQuery userQuery) {
        ListData listData = getService().page(userQuery);
        listData.setList(this.entityToDTO(listData.getList()));
        return success(listData);
    }

	@GetMapping({"/export"})
	@ApiOperation(value = "导出", notes = "导出API")
	public void export(BaseQuery pageQuery, HttpServletResponse response) {
		List<UserBo> list = getService().list(pageQuery, UserBo.class);
		ExcelUtil.exportExcel(list, "sheet1", UserBo.class, response);
	}

    protected UserDTO entityToDTO(User entity) {
        UserDTO userDTO = super.entityToDto(entity);
        if (Objects.nonNull(userDTO)) {
            userDTO.setRoles(userRoleService.getByUserId(userDTO.getId()));
            userDTO.setDepts(userDeptService.getDeptByUserId(userDTO.getId()));
            userDTO.setAvatar(fileFeignClient.tempUrl(userDTO.getId(), FileKey.AVATAR));
            userDTO.setPhoto(fileFeignClient.tempUrls(userDTO.getId(), FileKey.PHOTO));
         //   userDTO.setPermissions(rolePermissionService.getPermsByUserId(userDTO.getId()));
        }
        return userDTO;
    }


    protected List<UserDTO> entityToDTO(List<User> entityList) {
        List<UserDTO> dtoList = new ArrayList<>();
        if (CollUtil.isNotEmpty(entityList)) {
            Set<Long> ids = entityList.stream().map(User::getId).collect(Collectors.toSet());
            Map<String, String> avatarMap = new HashMap<>();
            Map<String, List<String>> photoMap = new HashMap<>();
            try {
                avatarMap = fileFeignClient.tempUrlMap(ids, FileKey.AVATAR);
                photoMap = fileFeignClient.tempUrlsMap(ids, FileKey.PHOTO);
            }catch (Exception ignored) {

            }

            Map<Long, List<UserRoleDTO>> roleMap = userRoleService.getByUserIds(entityList.stream().map(User::getId).collect(Collectors.toSet()));
            Map<String, String> finalAvatarMap = avatarMap;
            Map<String, List<String>> finalPhotoMap = photoMap;
            entityList.forEach(entity -> {
                UserDTO dto = DataConverter.convert(entity, UserDTO.class);
                dto.setRoles(roleMap.get(dto.getId()));
                dto.setAvatar(finalAvatarMap.get(FileKey.AVATAR + dto.getId()));
                dto.setPhoto(finalPhotoMap.get(FileKey.PHOTO + dto.getId()));
                dtoList.add(dto);
            });
        }
        return dtoList;
    }
}
